package com.example.demo1122.controller;

import com.alibaba.dashscope.aigc.generation.GenerationResult;
import com.alibaba.dashscope.exception.InputRequiredException;
import com.alibaba.dashscope.exception.NoApiKeyException;
import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.demo1122.DTO.StudentDTO;
import com.example.demo1122.DTO.TeacherDTO;
import com.example.demo1122.domain.LoginStudent;
import com.example.demo1122.domain.ResponseResult;
import com.example.demo1122.entity.*;
import com.example.demo1122.service.IClassstuService;
import com.example.demo1122.service.IConversationService;
import com.example.demo1122.service.IQuestionService;
import com.example.demo1122.service.IStudentService;
import io.reactivex.Flowable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;

import static org.apache.logging.log4j.util.Strings.isEmpty;


/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author baomidou
 * @since 2023-12-07
 */
@Controller
@RequestMapping("/student")
public class StudentController {

    @Autowired
    private IStudentService studentService;
    @Autowired
    private IClassstuService classstuService;
    @Autowired
    private IConversationService conversationService;
    @Autowired
    private IQuestionService questionService;
    @Autowired
    private PasswordEncoder passwordEncoder;
    private static final Logger logger = LoggerFactory.getLogger(StudentController.class);


    private String fromTokenGetStudenID(){
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        LoginStudent loginStudent = (LoginStudent) authentication.getPrincipal();
        String studentID = loginStudent.getStudent().getStudentID();
        return studentID;
    }
    //通过课堂导入文件来新增学生 check
    @PostMapping("/upload")
    @ResponseBody
    public ResponseResult uploadExcel(@RequestParam("file") MultipartFile file,
                                      @RequestParam(defaultValue = "0") Integer classID
    ) {
        if (file.isEmpty()) {
            return new ResponseResult(120, "文件为空");
        }
        try {
            InputStream inputStream = file.getInputStream();
            // 使用EasyExcel读取Excel文件数据
            List<Student> students = readExcel(inputStream);
            // 在这里将学生信息保存到学生表中
            return studentService.saveStudentList(students,classID);
            //在这里将classID和学生studentID保存到classstu表中
            //return new ResponseResult(126, "文件上传成功");
        } catch (Exception e) {
            e.printStackTrace();
            return new ResponseResult(127, "文件上传失败");
        }
    }
    private List<Student> readExcel(InputStream inputStream) {
        // 使用EasyExcel读取Excel文件数据
        List<Student> students = new ArrayList<>();
        // 使用 EasyExcel.read 方法传入输入流和数据分析监听器
        EasyExcel.read(inputStream, new AnalysisEventListener<Map<Integer, String>>() {
            @Override
            public void invoke(Map<Integer, String> data, AnalysisContext context) {
                // 'data' 是一个映射，包含每一行的单元格值，键是列索引，值是单元格的值
                // 假设 'studentID' 在第一列，'name' 在第二列
                String studentID = data.get(0);
                String name = data.get(1);
                Student student = new Student();
                student.setStudentID(studentID);
                student.setName(name);
                students.add(student);
            }

            @Override
            public void doAfterAllAnalysed(AnalysisContext context) {
                // 在读取完成后执行一些操作，如果需要的话
            }
        }).sheet().doRead();

        return students;
    }

    // 学生查看自己的信息
    @GetMapping("/profile")
    @ResponseBody
    public ResponseResult getProfile(){
        String studentID = fromTokenGetStudenID();
        Student student=studentService.getById(studentID);
        StudentDTO studentDTO=new StudentDTO();
        studentDTO.setStudentID(student.getStudentID());
        studentDTO.setName(student.getName());
        return new ResponseResult(1,"success", studentDTO);
        // return studentService.getProfile(studentID);
    }
    //学生修改学生信息 20240102
    @PostMapping("/update")
    @ResponseBody
    public ResponseResult updatemassage(@RequestParam String name) {


        try {
            String studentID= fromTokenGetStudenID();
            StudentDTO student=new StudentDTO();
            student.setStudentID(studentID);
            student.setName(name);
            // 新增或者更新
            return studentService.updateStudent(student);
        } catch (Exception e) {
            // 打印异常信息
            e.printStackTrace();
            // 处理异常，将异常信息放入ResponseResult对象返回
            return new ResponseResult<>(500, "Internal Server Error", null);
        }
    }

    //学生修改学生密码 20240102
    @PostMapping("/updatepassword")
    @ResponseBody
    public ResponseResult updatepassword(@RequestParam String password) {
        try {
            Student student=new Student();

            String studentID= fromTokenGetStudenID();
            student.setStudentID(studentID);
            student.setPassword(passwordEncoder.encode(password));
            // 新增或者更新
            return studentService.updateStudentpassword(student);
        } catch (Exception e) {
            // 打印异常信息
            e.printStackTrace();
            // 处理异常，将异常信息放入ResponseResult对象返回
            return new ResponseResult<>(500, "Internal Server Error", null);
        }
    }

    // 学生查看自己加入的所有课堂信息
    @PostMapping("/getclassinfo")
    @ResponseBody
    public ResponseResult getClassInfo(){
        try {
            String studentID = fromTokenGetStudenID();
            return studentService.getClassInfo(studentID);
        } catch (Exception e) {
            return new ResponseResult(0,"error",e);
        }
    }

    //管理员新增学生、老师通过课堂新增学生 check
    @PostMapping("/save")
    @ResponseBody
    public ResponseResult save(@RequestBody Student student,
                               @RequestParam(defaultValue = "0") Integer classID
    ) {
        if(isEmpty(student.getPassword())) {
            student.setPassword("123456");
        }
        try {
            String password = passwordEncoder.encode(student.getPassword());
            student.setPassword(password);

            // 新增或者更新
            return studentService.saveOrUpdateStudent(student,classID);
        } catch (Exception e) {
            // 打印异常信息
            e.printStackTrace();
            // 处理异常，将异常信息放入ResponseResult对象返回
            return new ResponseResult<>(500, "Internal Server Error", null);
        }
    }

    //管理员查看所有学生列表 check
    @GetMapping("/findall")
    @ResponseBody
    public List<StudentDTO> findAll() {
        List<Student> students = studentService.list();
        List<StudentDTO> studentDTOs = convertToDTOList(students);
        return studentDTOs;
    }

    private List<StudentDTO> convertToDTOList(List<Student> students) {
        // 编写转换逻辑，将 Student 转换为 StudentDTO
        List<StudentDTO> studentDTOs = new ArrayList<>();

        for (Student student : students) {
            StudentDTO studentDTO = new StudentDTO();
            studentDTO.setStudentID(student.getStudentID());
            studentDTO.setName(student.getName());

            // 如果有其他需要转换的字段，可以继续添加

            studentDTOs.add(studentDTO);
        }

        return studentDTOs;
    }

    //管理员删除单个学生数据 check
    @DeleteMapping("/{studentID}")
    @ResponseBody
    public ResponseResult delete(@PathVariable String studentID) {

        try {
            studentService.removeById(studentID);
            return new ResponseResult(156, "删除成功");
        } catch (Exception e) {
            e.printStackTrace();
            return new ResponseResult(157, "删除失败");
        }
    }

    //管理员批量删除学生 check
    @PostMapping("/del/batch")
    @ResponseBody
    public ResponseResult deleteBatchstu(@RequestBody List<String> studentIDs) { // [1,2,3]
        try {
            studentService.removeByIds(studentIDs);
            return new ResponseResult(1206, "删除成功");
        } catch (Exception e) {
            e.printStackTrace();
            return new ResponseResult(1207, "删除失败");
        }

    }
    //check
    @GetMapping("/page1")
    @ResponseBody
    public ResponseResult findPage1(@RequestParam Integer pageNum,
                                    @RequestParam Integer pageSize,
                                    @RequestParam(defaultValue = "") String studentID,
                                    @RequestParam(defaultValue = "") String name) {

        try {
            // 执行分页查询
            Page<StudentDTO> pagedto = studentService.findPage(pageNum,pageSize, studentID, name);
            // 创建包含分页结果的ResponseResult对象
            return new ResponseResult<>(166, "查询成功", pagedto.getRecords());
        } catch (Exception e) {
            e.printStackTrace();
            return new ResponseResult<>(167, "查询失败", null);
        }
    }


    //cly added
    // conversation
    // 创建conversation
    @PostMapping("/createconversation")
    @ResponseBody
    public ResponseResult createConversation(@RequestBody Conversation conversation){
        return conversationService.createConversation(conversation);
    }

    //TODO 返回某学生id下所有conversation
    //变动：删除路径中的学生ID与参数中传入学生ID，改为从token获取
    @PostMapping("/allconversation")
    @ResponseBody
    public ResponseResult getAllConversation(){
        String studentID= fromTokenGetStudenID();
        if (studentID == null){
            return new ResponseResult(0, "error", "未获取到学生ID");
        }
        return conversationService.selectStudentConversation(studentID);
    }

    //TODO 查询一个学生创建的conversation数量
    //变动：删除路径中的学生ID与参数中传入学生ID，改为从token获取
    @PostMapping("/conversationnum")
    @ResponseBody
    public ResponseResult getConversationNum(){
        String studentID= fromTokenGetStudenID();
        return conversationService.getConversationNum(studentID);
    }

    // 学生评价conversation质量
    @PostMapping("/evaluateconversation")
    @ResponseBody
    public ResponseResult evaluateConversation(@RequestBody Conversation conversation){
        return conversationService.evaluateConversation(conversation);
    }

    // 学生结束conversation
    @PostMapping("/endconversation")
    @ResponseBody
    public ResponseResult endConversation(@RequestBody Conversation conversation){
        return conversationService.endConversation(conversation);
    }

    //TODO 展示一个学生的所有会话记录
    @PostMapping("/showhistory")
    @ResponseBody
    public ResponseResult showHistory(@RequestBody Conversation conversation){
        return conversationService.showHistory(conversation);
    }

    // 根据classID、chapterID获取该学生的所有该章节下conversationID和title
    @PostMapping("/chapterconversationinfo")
    @ResponseBody
    public ResponseResult chapterConversationInfo(@RequestParam Integer classID, @RequestParam Integer chapterID){
        String studentID = fromTokenGetStudenID();
        return conversationService.chapterConversationInfo(classID, chapterID, studentID);
    }

    //questionService
    // 学生ask接口，返回千问模型输出
    @PostMapping("/ask")
    @ResponseBody
    public ResponseResult askLLM(@RequestBody Question question) throws NoApiKeyException, InputRequiredException {
        return questionService.askLLM(question);
    }

/*    @PostMapping(value = "/askstream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    @ResponseBody
    public Flowable<GenerationResult> askLLM_stream(@RequestBody Question question) throws NoApiKeyException, InputRequiredException {
        return questionService.askLLM_stream(question);
    }*/

    //TODO 返回某conversation下所有question answer内容
    @PostMapping("/showconversation/{conversationID}")
    @ResponseBody
    public ResponseResult showConversation(@PathVariable Integer conversationID){
        if (conversationID == null){
            return new ResponseResult(0, "error", "未接受到会话ID");
        }
        return questionService.showConversation(conversationID);
    }

    // 查询学生在某个对话下的所有question
    @PostMapping("/allquestion/{conversationID}")
    @ResponseBody
    public ResponseResult getAllQuestion(@PathVariable Integer conversationID){
        if (conversationID == null){
            return new ResponseResult(0, "error", "未接受到会话ID");
        }
        return questionService.selectConversationQuestion(conversationID);
    }

    // 查询学生在某个对话下的questionNum
    @PostMapping("/questionNum/{conversationID}")
    @ResponseBody
    public ResponseResult getQuestionNum(@PathVariable Integer conversationID){
        if (conversationID == null){
            return new ResponseResult(0, "error", "未接受到会话ID");
        }
        return questionService.getQuestionNum(conversationID);
    }

    // 学生评价question质量
    @PostMapping("/evaluatequestion")
    @ResponseBody
    public ResponseResult evaluateQuestion(@RequestBody Question question){
        return questionService.evaluateQuestion(question);
    }


    // （管理员？）删除单个学生与课堂的连接数据
    @DeleteMapping("/{classID}/{studentID}")
    @ResponseBody
    public ResponseResult delete(@PathVariable Integer classID, @PathVariable String studentID) {
        try {

            boolean result = classstuService.deleteStudentFromClass(classID, studentID);
            if(result) {
                return new ResponseResult(156, "删除成功");
            } else {
                return new ResponseResult(157, "删除失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return new ResponseResult(157, "删除失败，异常：" + e.getMessage());
        }
    }
    //批量删除学生与课堂间的联系，复选框
    @PostMapping("/classstu/del/batch")
    @ResponseBody
    public ResponseResult deleteBatch(@RequestBody List<Classstu> keys) {
        boolean result = classstuService.deleteStudentClasses(keys);
        if (result) {
            return new ResponseResult(200, "批量删除成功");
        } else {
            return new ResponseResult(500, "批量删除失败");
        }
    }

    @GetMapping("/findall/{classID}")
    @ResponseBody
    public List<StudentDTO> findAllByClassId(@PathVariable Integer classID) {

        List<Student> students = studentService.findStudentsByClassId(classID);
        List<StudentDTO> studentDTOs = convertToDTOList(students);
        return studentDTOs;
    }

    @GetMapping("/findallstudentbyclass/{classID}")
    @ResponseBody
    public ResponseResult findAllStudentsByClassId(@PathVariable Integer classID) {
        // 直接调用service层的方法并返回结果
        return studentService.findallStudentsByClassId(classID);
    }

    //分页+模糊查询，在某个课堂序号下
    @GetMapping("/page/class")
    @ResponseBody
    public ResponseResult findPageByClassId(@RequestParam Integer classID,
                                            @RequestParam Integer pageNum,
                                            @RequestParam Integer pageSize,
                                            @RequestParam(defaultValue = "") String studentID,
                                            @RequestParam(defaultValue = "") String name) {
        try {
            // 调用服务层方法执行查询
            Page<StudentDTO> page = studentService.findPageByClassId(pageNum, pageSize, classID, studentID, name);
            // 检查查询结果是否为空
            if (page.getRecords().isEmpty()) {
                return new ResponseResult<>(HttpStatus.NO_CONTENT.value(), "没有符合条件的学生", Collections.emptyList());
            } else {
                return new ResponseResult<>(HttpStatus.OK.value(), "查询成功", page.getRecords());
            }
        } catch (Exception e) {
            e.printStackTrace();
            return new ResponseResult<>(HttpStatus.INTERNAL_SERVER_ERROR.value(), "查询失败", null);
        }
    }

    //根据学生ID查询课堂
    //学生查看自己加入的课堂 20240102
    @GetMapping("/findalljoin")
    @ResponseBody
    public ResponseResult findAllclass() {
        String studentID= fromTokenGetStudenID();
        return studentService.findclassByStudentId(studentID);
    }
}

